
import pylab as p
import math

from bpsk_modular_bits import modular_bits_en_bpsk
from funciones import generar_bits, sumar_ruido_gaussiano_blanco, detectar_bayesianamente
from funciones import calcular_estado_markov_estacionario, calcular_estado_markov

N = 1000
alpha_0 = 0
alpha_1 = math.pi
A = 1
L = 8 
sigma2_W = 1
C_W = sigma2_W * p.identity(L)


def generar_y_detectar(generado, modulado_mas_ruido, lambda_01, lambda_11, calcular_P01, P_01=None):
    assert((calcular_P01 != None) or (P_01 != None))
        
    detectado = []
    error = []
    for i in range(N):
        
        if calcular_P01:
            P_01 = calcular_P01(lambda_01, lambda_11, p.array([1-lambda_01, lambda_01]), i)
            
        detectado_i = detectar_bayesianamente(modulado_mas_ruido[i * L:(i + 1) * L], A, alpha_0, alpha_1, C_W, P_01[0], P_01[1])
        detectado.append(detectado_i[0])
        error.append(detectado_i[1])

    contador = 0
    for i in range(N):
        if (generado[i] != detectado[i]):
            contador += 1       

    errores = contador / float(N)
    return errores

def realizar_experimento(generado, modulado_mas_ruido, lambda_01, lambda_11):
    estacionario = calcular_estado_markov_estacionario(lambda_01, lambda_11)
    
    err_estacionario = generar_y_detectar(generado, modulado_mas_ruido, lambda_01, lambda_11, None, estacionario)
    err_calculo = generar_y_detectar(generado, modulado_mas_ruido, lambda_01, lambda_11, calcular_estado_markov)

    print "lambda_01={} lambda_11={}".format(lambda_01, lambda_11)
    print "\t error_estacionario= {}".format(err_estacionario)
    print "\t error_calculo= {}".format(err_calculo)
    print ""

if __name__ == '__main__':
    print "error_estacionario: Error de deteccion usando [P0, P1] igual al estado estacionario de la cadena de markov"
    print "error_estacionario: Error de deteccion calculando [P0, P1] en cada bit a partir de la cadena de Markov"
    print ""
    
    # lambda_01 y lambda_11 diferentes
    lambda_01 = 0.8
    lambda_11 = 0.3
    generado = generar_bits(lambda_01, lambda_11, N)
    modulado = modular_bits_en_bpsk(generado, alpha_0, alpha_1, A, L)
    modulado_mas_ruido = sumar_ruido_gaussiano_blanco(modulado, sigma2_W)
    realizar_experimento(generado ,modulado_mas_ruido, lambda_01, lambda_11)
    
    # lambda_01+lambda_11=1
    lambda_01 = 0.4
    lambda_11 = 0.6
    generado = generar_bits(lambda_01, lambda_11, N)
    modulado = modular_bits_en_bpsk(generado, alpha_0, alpha_1, A, L)
    modulado_mas_ruido = sumar_ruido_gaussiano_blanco(modulado, sigma2_W)
    realizar_experimento(generado ,modulado_mas_ruido, lambda_01, lambda_11)
    
    # lambda_01+lambda_11=1
    lambda_01 = 0.3
    lambda_11 = 0.3
    generado = generar_bits(lambda_01, lambda_11, N)
    modulado = modular_bits_en_bpsk(generado, alpha_0, alpha_1, A, L)
    modulado_mas_ruido = sumar_ruido_gaussiano_blanco(modulado, sigma2_W)
    realizar_experimento(generado ,modulado_mas_ruido, lambda_01, lambda_11)
